/**
 * @file TimerWheel.hpp
 * @author 1102403684@qq.com
 * @brief
 * @version 0.1
 * @date 2024-09-30
 *
 * @copyright Copyright (c) 2024
 *
 */
#pragma once
#include <vector>
#include <unordered_map>
#include <cstdint>
#include <functional>
#include <unistd.h>
#include <iostream>
#include <sys/timerfd.h>
#include <memory>

#include "TimerTask.hpp"
#include "Channel.hpp"
#include "../common/logger.hpp"

class EventLoop; // 前置声明 因为时间轮要绑定到一个eventloop上，具体来说是绑定timerfd到loop上
class TimerWheel
{
public:
    TimerWheel() = default;
    TimerWheel(EventLoop *loop) : capacity_(60), tick_(0), wheel_(capacity_),
                                  loop_(loop), timerfd_(create_timerfd()), 
                                  timer_channel_(std::make_unique<Channel>(loop_, timerfd_))
    {
        //一旦触发读事件，会调用ontime函数
        timer_channel_->set_read_callback(std::bind(&TimerWheel::on_time, this));
        timer_channel_->enable_read_event();

        LOG_TRACE("timer_channel 初始化成功 占用fd {}", timer_channel_->get_fd());
    }
    void TimerAddInLoop(uint64_t id, uint32_t delay, const TaskFunc &task_func);
    void TimerRefreshInLoop(uint64_t id);
    void TimerCancelInLoop(uint64_t id);
    bool HasTimer(uint64_t id)
    {
        auto it = timers_.find(id);
        if(it == timers_.end()){
            return false;
        }
        return true;
    }

    // 每秒钟执行一次
    void runTimerTask()
    {
        LOG_TRACE("tick 为：{}， 当前tick的任务数量 {} ", tick_, wheel_[tick_].size());
        tick_ = (tick_ + 1) % capacity_;
        wheel_[tick_].clear();
    }

private:

    //很多定时任务设计对连接的io操作，因此需要考虑线程安全所以添加是使用TimerAdd
    void TimerAdd(uint64_t id, uint32_t delay, const TaskFunc &task_func)
    {
        TimerTask::ptr pt(new TimerTask(id, delay, task_func));
        pt->setRelease(std::bind(&TimerWheel::removeTimer, this, id));

        timers_[id] = TimerTask::ptr_weak(pt);

        int pos = (tick_ + delay) % capacity_;
        wheel_[pos].push_back(pt);

        // LOG_DEBUG("添加了一个定时任务 {} 当前pos {} 任务数量 {}", id, pos, wheel_[pos].size());
    }

    
    void TimerRefresh(uint64_t id)
    {
        auto it = timers_.find(id);
        if (it == timers_.end())
        {
            LOG_DEBUG("没找到定时任务");
            return; // 没找到定时任务
        }
        TimerTask::ptr ptr = it->second.lock();
        int delay = ptr->DelayTime();
        int pos = (tick_ + delay) % capacity_;
        wheel_[pos].push_back(ptr);
        LOG_TRACE("刷新了一个定时任务 {} 当前 pos {} 任务数量 {}", id, pos, wheel_[pos].size());
    }


    /**
     * 取消一个定时任务
     */
    void TimerCancel(uint64_t id)
    {
        auto it = timers_.find(id);
        if (it == timers_.end())
        {
            LOG_DEBUG("定时任务取消失败: 未找到定时任务 {}", id);
            return; 
        }

        TimerTask::ptr ptr = it->second.lock();
        if(ptr)
        {
            LOG_TRACE("取消了一个定时任务");
            ptr->Cancel();
        }
        
    }

    void removeTimer(uint64_t id)
    {
        LOG_DEBUG("remove timerTask");
        timers_.erase(id);
    }

    static int create_timerfd()
    {
        // 创建 timerfd
        int timefd = timerfd_create(CLOCK_MONOTONIC, 0);
        if (timefd < 0)
        {
            perror("timerfd_create error");
            return -1;
        }

        // 设置定时器触发时间
        struct itimerspec itime;
        itime.it_value.tv_sec = 1; // 第一次1秒后触发
        itime.it_value.tv_nsec = 0;
        itime.it_interval.tv_sec = 1; // 之后每1秒触发一次
        itime.it_interval.tv_nsec = 0;

        // 检查 timerfd_settime 的返回值
        if (timerfd_settime(timefd, 0, &itime, NULL) < 0)
        {
            perror("timerfd_settime error");
            close(timefd);
            return -1;
        }

        return timefd;
    }


    int read_timerfd()
    {
        uint64_t times;
        // 使用 sizeof(times) 来保证读取正确大小的数据
        int ret = read(timerfd_, &times, sizeof(times));
        if (ret < 0) {
            perror("read error");
            close(timerfd_);
            abort();
        }
        return ret;
    }

    void on_time()
    {
        int nums = read_timerfd();
        for(int i = 0;i<nums;i++){
            runTimerTask();
        }
    }

private:
    int tick_;     // 当前位置
    int capacity_; // 轮盘最大数量
    std::vector<std::vector<TimerTask::ptr>> wheel_;
    std::unordered_map<uint64_t /*定时器任务id*/, TimerTask::ptr_weak> timers_;

    /*滴答功能*/
    int timerfd_; // 可读事件回调：读取计时器，执行定时任务
    EventLoop *loop_;
    std::unique_ptr<Channel> timer_channel_;
};